#include "common.h"
#include "jszt_cnn.h"
#include "cnntools.h"
void test_js_mm();
extern Golad_CNN * gcnn;       //全局参数, 私用
void test_cnn(unsigned char * test_buff, int CPUS) {
    fflush(stdout);  
    setvbuf(stdout,NULL,_IONBF,0);

    jszt_init(CALCULAT_CPU, CPUS);

    printf("test1 \n");

    CNN_PARA cPara = { 0 }; 

    cPara.width = 1024;
    cPara.height = 1024;
    // cPara.width = 60;
    // cPara.height = 60;
    int total_len = cPara.width*cPara.height;
    uint8 *stream = (uint8 *)malloc(total_len);
    uint8 *streamTemp = (uint8 *)malloc(total_len);

    if(NULL == stream) {
        printf("err stream NULL");
        exit(-1);
    }   

    memset(stream, 0x0, total_len);

    cPara.ckrlen[0] = 9;
    cPara.ckrlen[1] = 5;
    cPara.ckrlen[2] = 3;

    int cnnker_len = cPara.ckrlen[0] + cPara.ckrlen[1] + cPara.ckrlen[2] + cPara.ckrlen[4];
    cnnker_len *= cnnker_len;

    uint8 *cnnker = (uint8 *)malloc(cnnker_len);
    if(NULL == cnnker) {
        printf("err dstream NULL");
        exit(-1);
    }
    memset(cnnker, 0x0, cnnker_len);


    cPara.stream = stream;
    cPara.cnnker = cnnker;

    printf("width: %d, height: %d, total_len %d \n", cPara.width, cPara.height, total_len);
    printf("cnnker_len: { %d %d %d %d } =>: %d \n", cPara.ckrlen[0],cPara.ckrlen[1],cPara.ckrlen[2],cPara.ckrlen[3], cnnker_len);
    printf("stream %p, dstream: %p, cnnker: %p, cpara: %p \n", cPara.stream, cPara.dstream, cPara.cnnker, &cPara);

    int i = 0, j = 0; 
    uint8 * ptr = cPara.stream;
    // uint8 * ptr1 = cPara.dstream;
    int cnt = 0;
    for(i = 0; i < cPara.height; i++) {
        for(j = 0; j < cPara.width; j++) {
            // if(i == j) {
            //     *ptr = cnt++;
            // }

            // //验证验证数据头和尾部
            // if(j==0) {
            //     *ptr = i;
            //     // *ptr1 = i;
            // }
            // if(j==cPara.height - 1) {
            //     *ptr = 0xAA;
            //     // *ptr1 = 0xBB;
            // } 

            *ptr =  rand() % 6; //生成随机数

            *ptr++;
            // *ptr1++;
        }
    }

    cnt = 0;
    ptr = cPara.cnnker;
    while(1) {
        if(cPara.ckrlen[cnt] == 0)
            break;

        for(i = 0; i < cPara.ckrlen[cnt]; i++) {
            for(j = 0; j < cPara.ckrlen[cnt]; j++) {
                if(i == j) {
                    *ptr = 0x1;
                }
                *ptr++;
            }
        }
        cnt++;
    }

    memset(cPara.stream, 0x0, cPara.width*cPara.height);
    memcpy(cPara.stream, test_buff, cPara.width*cPara.height);

    printf("start run \n");

    jszt_setReady();

#if 1
    cnt = 10;
    struct timeval tv; 
    int startTimes, endTimes, diff; 
    gettimeofday(&tv, NULL);

    startTimes = tv.tv_sec;
    int times = 0;
    memcpy(streamTemp, cPara.stream, cPara.height*cPara.width);
    while(times++ < cnt) {
        // 给定随机数, rand 比较耗费计算机性能
        ptr = cPara.stream;
        // memcpy(cPara.stream, streamTemp, cPara.height*cPara.width); 
        for(i = 0; i < cPara.height; i++) {
            for(j = 0; j < cPara.width; j++) {
                *ptr++ =  rand() % 10; //生成随机数
            }
        }

        // printHex1(cPara.cnnker, 81, 9, "cpara.stream");
        // printHex1(cPara.stream, 120, 60, "cpara.stream");
        if(jszt_CNN(&cPara) != 0) {
            printf("err \n");
        }
        // writeWithIndex(&cPara, times);
    }

    gettimeofday(&tv,NULL);
    endTimes = tv.tv_sec;

    diff = endTimes - startTimes;       // 秒数

    LOG_DEBUG("cnt -> %d, diff: %ds, times: %d", cnt, diff, times - 1);
    TH_STATUS * th_status = gcnn->tstatus;
    cnt = CPUS;
    while (cnt-- > 0)
    {
       LOG_DEBUG("thread_index: %d , times: %d ", th_status->thread_index, th_status->total_times);
       *th_status++;
    }
    
    jszt_setEnd();

    // while(1) {
    //     sleep(1);
    // }
    
#endif
    jszt_destroy();
}

void test11() {
    unsigned char * test_buff = (unsigned char *) malloc(1024*1024);
    int fd = open("./old.bat", O_RDONLY);
    if(fd <= 0) {
        printf("Error can not open file \n");
        exit(0);
    }
    
    int rlen = read(fd, test_buff, 1024*1024);
    printf("read file: %d, fd: %d \n", rlen, fd);
    if(rlen < 0) {
        printf("error: %s \n", strerror(errno));
        exit(0);
    }
    close(fd);
    // printHex1(test_buff, 3600, 60, "test_buff");

    test_cnn(test_buff, 2);
}
void check_out();
int main(int argc, char const *argv[])
{
    // check_out(argc, argv);
    test11();
    return 0;
}

void check_out(int argc, char const *argv[]) {
    printf("eg: ./a.out stream.bin kstream.bin dstream.bin w1024 h1024 1\n");
    if(argc != 7) {
        printf("Para is ERROR \n");
        return ;
    }

    int CPUS = atoi(argv[6]);
    CNN_PARA cPara = { 0 }; 
    cPara.width = (short)atoi(argv[4]);
    cPara.height = (short)atoi(argv[5]);
    cPara.ckrlen[0] = (uint8)atoi(argv[6]);

    int fd1 = open(argv[1], O_RDONLY);
    int fd2 = open(argv[2], O_RDONLY);
    int fd3 = open(argv[3], O_RDONLY);

    if(fd1 < 0 || fd2 < 0 || fd3 < 0) {
        LOG_DEBUG("file not exit");
    }

    int cnnkner_len = file_size(argv[2]);
    if(cnnkner_len <= 0) {
        LOG_ERROR("cnnkner len is error, cnnkner len: %d ", cnnkner_len);
        exit(0);
    }

    int i = 10;
    while(i-- > 0) {
        if(i*i == cnnkner_len) {
            cPara.ckrlen[0] = i;
        }
    }

    if(cPara.ckrlen[0] <= 0) {
        LOG_ERROR("cnnkner len is error, cnnkner len: %d ", cPara.ckrlen[0]);
        exit(0);
    }

    int dstream_len = file_size(argv[3]);
    int temp111 = (cPara.width - cPara.ckrlen[0] + 1)*(cPara.height - cPara.ckrlen[0] + 1);
    if(dstream_len < temp111) {
        LOG_ERROR("dstream len check len is error, flen len: %d, cval: %d ", dstream_len, temp111);
        exit(0);
    }

    cPara.stream  = (uint8 *)malloc(cPara.width*cPara.height);
    cPara.cnnker  = (uint8 *)malloc(cPara.ckrlen[0]*cPara.ckrlen[0]);
    cPara.dstream = (uint8 *)malloc(dstream_len);

    int rlen = 0;
    rlen = read(fd1, cPara.stream, cPara.width*cPara.height);
    if(rlen != cPara.width*cPara.height) {
        LOG_ERROR("fd1, rlen: %d, nlen: %d", rlen, cPara.width*cPara.height);
        exit(-1);
    }
    rlen = read(fd2, cPara.cnnker, cPara.ckrlen[0]*cPara.ckrlen[0]);
    if(rlen != cPara.ckrlen[0]*cPara.ckrlen[0]) {
        LOG_ERROR("fd2, rlen: %d, nlen: %d", rlen, cPara.ckrlen[0]*cPara.ckrlen[0]);
        exit(-1);
    }

    rlen = read(fd3, cPara.dstream, dstream_len);
    if(rlen != dstream_len) {
        LOG_ERROR("fd3, rlen: %d, nlen: %d", rlen, dstream_len);
        exit(-1);
    }

    LOG_INFO("width:   \t%d ", cPara.width);
    LOG_INFO("height:  \t%d ", cPara.height);
    LOG_INFO("ccnklen: \t%d ", cPara.ckrlen[0]);
    LOG_INFO("CPU nums:\t%d ", cPara.ckrlen[0]);

    jszt_init(CALCULAT_CPU, CPUS);
    LOG_INFO("%d CPU are start run to check ... , ", CPUS);
    LOG_INFO("Error check only show 6 rows ");

    if(jszt_CNN(&cPara) != 0) {
        printf("err \n");
    }
    LOG_INFO("check end ", CPUS);
    jszt_setEnd();
    jszt_destroy();
}